package com.hello.rabbitlistener;

import com.Constants;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.amqp.rabbit.annotation.MultiRabbitBootstrapConfiguration;
import org.springframework.amqp.rabbit.annotation.RabbitBootstrapConfiguration;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

/**
 * 添加@EnableRabbit注解之后会在程序启动时自动注册上交换机，队列等，理由是：
 * 1.此注解等价于RabbitListenerConfigurationSelector
 * 2.上面的类会导入RabbitBootstrapConfiguration
 * 3. 上面的类会导入RabbitListenerEndpointRegistry
 * 4.此配置类实现了lifecycle接口，在此类的start方法添加断点，你会发现它会调用连接工厂的createConnection方法
 * 5.当创建连接时会执行连接连接监听器，监听器会间接调用RabbitAdmin的initialize方法，这点在RabbitAdmin的afterPropertiesSet方法可以看到
 * 6.initialize方法会注册队列，交换机，绑定等
 */
@Configuration
//第一步：这个注解默认要求有名字为rabbitListenerContainerFactory的bean
@EnableRabbit
@ComponentScan("com.hello.rabbitlistener")
public class HelloRabbitListenerMqConfiguration {


    @Bean
    public CachingConnectionFactory connectionFactory() {
        return new CachingConnectionFactory("localhost");
    }

    @Bean
    public RabbitAdmin amqpAdmin() {
        return new RabbitAdmin(connectionFactory());
    }


    @Bean
    public Queue myQueue() {
        return new Queue(Constants.QUEUE_NAME);
    }


    @Bean
    public RabbitTemplate rabbitTemplate() {
        return new RabbitTemplate(connectionFactory());
    }

    /**
     * 第二步：这个bean是与EnableRabbit注解配合使用的
     *
     *   除了SimpleRabbitListenerContainerFactory还有DirectRabbitListenerContainerFactory
     *   他们都是RabbitListenerContainerFactory接口的实现类，是用来创建MessageListenerContainer类型的
     *
     *  SimpleRabbitListenerContainerFactory创建SimpleMessageListenerContainer
     *    DirectRabbitListenerContainerFactory创建DirectMessageListenerContainer
     *
     *    工厂创建出的MessageListenerContainer对象并没有注册到spring容器中,
     *    但通过RabbitListenerEndpointRegistry可以获取到
     * @return
     */
    @Bean
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(){
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory());
        //factory.setConcurrentConsumers(2);
        //factory.setMaxConcurrentConsumers(2);
       // factory.setPrefetchCount(1);
        return factory;
    }
}
